import getSpecifiedFile from './lib/files/getSpecifiedFile'
import fs from 'fs'
import { extractI18nKeys, findDifferentKeys, getPrettierParser, sortJSON } from './lib/utils/utils'
import { get, set, uniq } from 'lodash'
import prettier from 'prettier'
import Collector from './external/i18n-extract-cli/src/collector'
import transform from './external/i18n-extract-cli/src/transform'
import path from 'path'
import { FileExtension } from './external/i18n-extract-cli/types'
import config from './external/i18n-extract-cli/src/default.config'
import crypto from 'crypto'
import { fyFetchApi } from './lib/utils/fyFetchApi'
import createContext from './lib/core/createContext'
import log from './external/i18n-extract-cli/src/utils/log'
export async function i18nTools(contextConfig: ContextType): Promise<void> {
  // TODO 获取所有文件,后续根据git提交变更  getChangeFiles
  const files = await getSpecifiedFile({
    projectPath: contextConfig.projectPath,
    dirPath: contextConfig.globalPath || '',
    includeDir: contextConfig.includeDir,
    fileSuffix: contextConfig.exts,
    excludeFileOrDir: contextConfig.excludeFileOrDir || []
  })
  const context = await createContext(files, contextConfig)
  const primaryLang = JSON.parse(fs.readFileSync(contextConfig?.lang?.primaryFile?.path || '', 'utf-8'))
  const useLangKeys: string[] = []
  /** ======== 处理文件 start ========= */
  log.info(`=== Total files === ${context?.files?.length || 0}`)
  let index = 0
  for (let file of context?.files || []) {
    const vueContent = fs.readFileSync(file.fullPath, 'utf-8')
    Collector.resetCountOfAdditions()
    Collector.setCurrentCollectorPath(file.fullPath)
    const ext = path.parse(file.fullPath).ext.replace('.', '') as FileExtension
    const keyMap = Collector.getCurrentFileKeyMap()
    let vueTransform = transform(vueContent, ext, config.rules, file.fullPath)
    const keys = Object.keys(keyMap)
    const parser = getPrettierParser(ext)
    Collector.resetCurrentFileKeyMap()
    // 文件提取
    let vueTransformContent = prettier.format(vueTransform.code, {
      parser: parser,
      ...contextConfig.prettier
    })
    // 如果存在中文处理
    if (keys.length > 0) {
      log.verbose(`:::Chinese language needs to be extracted:::  keys => ${keys.length} `)
      const zh = keys.reduce(
        (pre: { enumStraight: Record<string, string>; enumReverseSide: Record<string, string> }, key) => {
          if (!/@\+\+@(.*?)@\+\+@/g.test(key)) {
            console.log(key)
            throw new Error('@++@@++@ is not found')
          }
          const rKey = key.replace(/@\+\+@(.*?)@\+\+@/g, '$1')
          const md5Val = crypto.createHash('md5').update(rKey).digest('hex')
          let len = 8
          let valueKey = `i18n_${md5Val.substring(0, (len += 2))}`
          let oldVal = get(primaryLang, key)
          while (oldVal && oldVal !== rKey) {
            valueKey = `i18n_${md5Val.substring(0, (len += 2))}`
            oldVal = get(primaryLang, key)
            if (len > md5Val.length) {
              throw new Error(`${rKey} already exists in ${oldVal}`)
            }
          }
          pre['enumStraight'][valueKey] = rKey
          pre['enumReverseSide'][key] = valueKey
          set(primaryLang, valueKey, rKey)
          // primaryLang[valueKey] = rKey
          return pre
        },
        {
          enumStraight: {},
          enumReverseSide: {}
        }
      )
      Object.keys(zh.enumReverseSide)
        .sort((a, b) => {
          return b.length - a.length
        })
        .forEach((key) => {
          // 此处存在bug
          while (vueTransformContent.indexOf(key) !== -1) {
            vueTransformContent = vueTransformContent.replace(key, zh.enumReverseSide[key])
          }
        })

      /** =========== 提取页面语言 与 主语言对比 start =========== */
      vueTransformContent = prettier.format(vueTransformContent, {
        parser: parser,
        ...contextConfig.prettier,
        // 提取
        printWidth: 99999
      })

      /** =========== 提取页面语言 与 主语言对比 end =========== */

      vueTransformContent = prettier.format(vueTransformContent, {
        parser: parser,
        ...contextConfig.prettier
      })
      fs.writeFileSync(file.fullPath, vueTransformContent)
    }
    // 提取i18n页面key
    const pageKeys = extractI18nKeys(vueTransformContent, ext)
    useLangKeys.push(...pageKeys)

    pageKeys.forEach((key) => {
      const value = get(primaryLang, key)
      if (!value) {
        log.error(`存在引用的key但是没有语言 ${key} ${file.fullPath}`)
      }
    })

    log.info(`=== File Path === ${file.fullPath}`)
    log.info(`=== File processing completed === ${index++}/${context?.files?.length || 0}`)
  }
  log.success(`=== files save success ===`)

  // 自动删除未被引用的 key
  const primaryLangKeys = Object.keys(primaryLang)
  const useLangKeysSet = uniq(useLangKeys)
  if (contextConfig?.autoRemoveUncited === true) {
    primaryLangKeys
      .filter((item) => !useLangKeysSet.includes(item))
      .forEach((key) => {
        log.warning(`删除语言中未被引用的key: ${key}`)
        delete primaryLang[key]
      })
  } else {
    if (useLangKeysSet.length != primaryLangKeys.length) {
      log.warning(
        `主语言中的语言数量与提前出不一致,请检查主语言是否删除了key，${primaryLangKeys.length} ${useLangKeysSet.length}`
      )
      primaryLangKeys
        .filter((item) => !useLangKeysSet.includes(item))
        .forEach((key) => {
          log.warning(`主语言中的语言数量与提前出不一致,请检查主语言是否删除了key，${key}`)
        })
    }
  }

  /** ======  主语言保存  ======= */
  fs.writeFileSync(
    contextConfig?.lang?.primaryFile?.path || '',
    prettier.format(JSON.stringify(sortJSON(primaryLang), null, 4), {
      parser: 'json',
      ...contextConfig.prettier
    })
  )
  log.success(`=== primaryLang save success ===`)

  /** ======== 主语言同步翻译至其他语言 start ======= */
  if (!contextConfig.translate?.bd) {
    log.error('contextConfig.translate.bd not configured')
  } else {
    for (let item of contextConfig.lang?.syncFile || []) {
      const syncLang = JSON.parse(fs.readFileSync(item.path, 'utf-8') || '{}')
      const { addKey, delKey } = findDifferentKeys(primaryLang, syncLang)
      for (let key of addKey) {
        const primaryText = get(primaryLang, key)
        const data = await fyFetchApi(primaryText, item.lang, contextConfig)
        const dst = data?.[0]?.dst
        if (dst) {
          syncLang[key] = dst
          log.verbose(`i18n:${item.lang}:add ${key}`)
          log.verbose(`${primaryText} ==> ${dst}`)
        } else {
          log.verbose(`Translation failed ${key}`)
        }
      }
      delKey.forEach((key) => {
        const keys = key.split('.')
        keys.reduce((pre: Record<string, any>, cur, index) => {
          if (index == keys.length - 1) {
            delete pre[cur]
            return pre
          }
          return pre[cur]
        }, syncLang)
        log.verbose(`del { syncLang } key ${key}`)
      })
      fs.writeFileSync(
        item.path,
        prettier.format(JSON.stringify(syncLang, null, 4), {
          parser: 'json',
          ...contextConfig.prettier
        }),
        'utf-8'
      )
    }
  }
  /** ======== 主语言同步翻译至其他语言 end ======= */
  log.success('i18n work success')
}
